'''
作者：Zion Loh
版本：V1.0.1
License: MIT
使用该源代码请附带作者及版权信息！
'''

import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import ipaddress
import csv

results = []

def ipv4_to_nat64(ipv4):
    # NAT64前缀64:ff9b::/96 + IPv4地址直接拼接
    return "64:ff9b::" + str(ipv4)

def ipv4_to_6to4(ipv4):
    # 6to4格式 2002:xxxx:xxxx:: ，xxxx是IPv4的十六进制高低16位
    packed = ipv4.packed
    return f"2002:{packed[0]:02x}{packed[1]:02x}:{packed[2]:02x}{packed[3]:02x}::"

def ipv4_to_isatap(ipv4):
    # ISATAP地址 fe80::5efe:IPv4
    return f"fe80::5efe:{ipv4}"

def ipv6_to_ipv4(ipv6_str):
    try:
        ipv6 = ipaddress.IPv6Address(ipv6_str)
        s = str(ipv6).lower()
        if s.startswith("64:ff9b::"):
            # NAT64后96位是IPv4
            ipv4_part = ipv6.packed[-4:]
            ipv4_addr = ipaddress.IPv4Address(ipv4_part)
            return "NAT64 → " + str(ipv4_addr), str(ipv4_addr)
        elif s.startswith("2002:"):
            parts = s.split(":")
            if len(parts) < 3:
                return "6to4格式错误", None
            hex_str = parts[1] + parts[2]
            ipv4_bytes = bytes.fromhex(hex_str)
            ipv4_addr = ipaddress.IPv4Address(ipv4_bytes)
            return "6to4 → " + str(ipv4_addr), str(ipv4_addr)
        elif "5efe" in s:
            idx = s.find("5efe")
            ipv4_hex = s[idx+5:]
            # 处理可能有冒号分隔的 IPv4 hex
            parts = ipv4_hex.split(":")
            bytes_list = []
            for p in parts:
                if p:
                    try:
                        bytes_list.append(int(p,16))
                    except:
                        pass
            if len(bytes_list) == 4:
                ipv4_addr = ipaddress.IPv4Address(bytes(bytes_list))
                return "ISATAP → " + str(ipv4_addr), str(ipv4_addr)
            else:
                # 无法解析完整IPv4，返回原字符串
                return "ISATAP → " + ipv4_hex, None
        else:
            return "无法识别的 IPv6 转换类型", None
    except Exception as e:
        return f"错误: {e}", None

def analyze_ipv4(ipv4_cidr):
    try:
        net = ipaddress.IPv4Network(ipv4_cidr, strict=False)
        hosts = list(net.hosts())
        info = [
            f"IPv4 地址: {ipv4_cidr}",
            f"网络地址: {net.network_address}",
            f"广播地址: {net.broadcast_address}",
            f"子网掩码: {net.netmask}",
            f"主机数量: {len(hosts)}",
        ]
        if hosts:
            info.append(f"可用范围: {hosts[0]} - {hosts[-1]}")
        else:
            info.append("无可用主机地址")
        info.append("-" * 40)
        return "\n".join(info)
    except Exception as e:
        return f"[错误] {ipv4_cidr}: {e}"

def process_single_ip():
    results.clear()
    ip = entry.get().strip()
    if not ip:
        return
    try:
        if "/" in ip:
            # IPv4子网分析
            output(analyze_ipv4(ip))
        else:
            try:
                ipv4 = ipaddress.IPv4Address(ip)
                nat64 = ipv4_to_nat64(ipv4)
                s6to4 = ipv4_to_6to4(ipv4)
                isatap = ipv4_to_isatap(ipv4)
                lines = [
                    f"原始 IPv4: {ipv4}",
                    f"NAT64: {nat64}",
                    f"6to4: {s6to4}",
                    f"ISATAP: {isatap}",
                    "-" * 40
                ]
                results.append([str(ipv4), nat64, s6to4, isatap])
                output("\n".join(lines))
            except ipaddress.AddressValueError:
                # IPv6 转 IPv4
                ipv6_result, extracted_ipv4 = ipv6_to_ipv4(ip)
                lines = [
                    f"原始 IPv6: {ip}",
                    ipv6_result,
                    "-" * 40
                ]
                output("\n".join(lines))
                if extracted_ipv4:
                    # 记录 IPv4 地址到结果，方便导出
                    results.append([extracted_ipv4, "", "", ""])
    except Exception as e:
        output(f"[错误] 无效地址: {e}")

def output(text):
    text_area.insert(tk.END, text + "\n")
    text_area.see(tk.END)

def import_file():
    results.clear()
    file_path = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt *.csv")])
    if not file_path:
        return
    try:
        with open(file_path, "r") as f:
            lines = [line.strip() for line in f if line.strip()]
            for line in lines:
                entry.delete(0, tk.END)
                entry.insert(0, line)
                process_single_ip()
    except Exception as e:
        messagebox.showerror("导入错误", str(e))

def export_results():
    content = text_area.get("1.0", tk.END).strip()
    if not content:
        messagebox.showinfo("提示", "没有数据可导出。")
        return
    file_path = filedialog.asksaveasfilename(
        defaultextension=".txt",
        filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
    )
    if not file_path:
        return
    try:
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(content)
        messagebox.showinfo("成功", f"结果已保存到 {file_path}")
    except Exception as e:
        messagebox.showerror("导出错误", str(e))


def center_window(win, width=720, height=480):
    screen_width = win.winfo_screenwidth()
    screen_height = win.winfo_screenheight()
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    win.geometry(f"{width}x{height}+{x}+{y}")


# GUI Setup
root = tk.Tk()
root.title("IP 地址智能转换工具")
root.resizable(False, False)
center_window(root, 720, 420)

entry = tk.Entry(root, width=50)
entry.pack(pady=10)

btn_frame = tk.Frame(root)
btn_frame.pack()

tk.Button(btn_frame, text="IPv4 子网分析", command=lambda: output(analyze_ipv4(entry.get()))).grid(row=0, column=0, padx=5)
tk.Button(btn_frame, text="IPv4 → 多种 IPv6", command=process_single_ip).grid(row=0, column=1, padx=5)
tk.Button(btn_frame, text="IPv6 → IPv4", command=process_single_ip).grid(row=0, column=2, padx=5)
tk.Button(btn_frame, text="导入文件", command=import_file).grid(row=0, column=3, padx=5)
tk.Button(btn_frame, text="导出结果", command=export_results).grid(row=0, column=4, padx=5)

text_area = scrolledtext.ScrolledText(root, width=90, height=20)
text_area.pack(pady=10)

root.mainloop()
